package org.fastsyncer.parser.framework;

import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;

import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.parser.ldap.LdapParser;
import org.fastsyncer.parser.mysql.MysqlParser;
import org.fastsyncer.parser.oracle.OracleParser;
import org.fastsyncer.parser.redis.RedisParser;
import org.fastsyncer.parser.sql.SqlMysqlParser;
import org.fastsyncer.parser.sql.SqlOracleParser;
import org.fastsyncer.parser.sqlserver.SqlServerParser;
import org.fastsyncer.parser.webservice.WebserviceParser;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ParserFactory {

    private static volatile ParserFactory instance = null;

    private ParserFactory() {
    }

    public static ParserFactory getInstance() {
        if (null == instance) {
            synchronized (ParserFactory.class) {
                if (null == instance) {
                    instance = new ParserFactory();
                }
            }
        }
        return instance;
    }

    private static final Logger logger = LoggerFactory.getLogger(ParserFactory.class);

    // 存放连接器实例
    private final static Map<String, Parser> MAP = new ConcurrentHashMap<String, Parser>();
    
    static {
        MAP.put(ConnectorConstant.MYSQL_CONNECTOR, MysqlParser.getInstance());
        MAP.put(ConnectorConstant.ORACLE_CONNECTOR, OracleParser.getInstance());
        MAP.put(ConnectorConstant.SQLSERVER_CONNECTOR, SqlServerParser.getInstance());
        MAP.put(ConnectorConstant.SQL_MYSQL_CONNECTOR, SqlMysqlParser.getInstance());
        MAP.put(ConnectorConstant.SQL_ORACLE_CONNECTOR, SqlOracleParser.getInstance());
        MAP.put(ConnectorConstant.LDAP_CONNECTOR, LdapParser.getInstance());
        MAP.put(ConnectorConstant.REDIS_CONNECTOR, RedisParser.getInstance());
        MAP.put(ConnectorConstant.WS_CONNECTOR, WebserviceParser.getInstance());
    }
    
    /**
     * 批量插入数据源到目标源
     * @param mappingTask
     *            同步任务
     * @param pos
     *            开始位置/结束位置
     * @param reasonQuene
     *            错误记录队列
     * @return Integer[]{ 总数total, 成功数success }
     * @throws Exception
     */
    public Integer[] parse(MappingTask mappingTask, Integer[] pos, Queue<JSONObject> reasonQuene) throws Exception {
        // 1.获取数据源数据,[{ID=123, NAME=张三11}, {ID=321, NAME=李四},...]
        String connector = mappingTask.getSourceMapping().getConnector();
        Parser parser = MAP.get(connector);
        List<Map<String, Object>> rows = parser.batchQuery(mappingTask, pos[0], pos[1]);

        // 2.数据转换
        List<Map<String, Object>> convertList = ConvertFactory.convert(mappingTask, rows);
        if(null == convertList){
            return new Integer[] { 0, 0};
        }

        // 3.同步给目标源
        // 批量插入
        connector = mappingTask.getTargetMapping().getConnector();
        parser = MAP.get(connector);
        Integer[] batchInsert = parser.batchInsert(mappingTask, convertList, pos, reasonQuene);
        
        convertList = null;
        rows = null;
        return batchInsert;
    }

    /**
     * 增量同步到目标源
     * @param mappingTask
     *            同步任务
     * @param rowJson
     *            增量数据
     * @return 执行成功/失败
     * @throws Exception
     */
    public boolean parse(MappingTask mappingTask, JSONObject rowJson) throws Exception {
        String eventType = rowJson.getString("eventType");
        JSONArray before = rowJson.getJSONArray("before");
        JSONArray after = rowJson.getJSONArray("after");
        
        // 1.数据格式转换
        JSONArray msg = null;
        Map<String, Object> beforeData = null;
        switch (eventType) {
        case ConnectorConstant.OPERTION_UPDATE:
            msg = after;
            beforeData = ConvertFactory.convertJSONArrayToMap(before);
            break;
        case ConnectorConstant.OPERTION_INSERT:
            msg = after;
            break;
        case ConnectorConstant.OPERTION_DELETE:
            msg = before;
            break;
        default:
            break;
        }
        
        // 2.将JSONArray格式的数据转换为map对象
        Map<String, Object> data = ConvertFactory.convertJSONArrayToMap(msg);
        if (null == data || data.isEmpty()) {
            return false;
        }
        Map<String, Object> row = ConvertFactory.convert(mappingTask, eventType, data, beforeData);
        logger.info(row.toString());

        String connector = mappingTask.getTargetMapping().getConnector();
        Parser parser = MAP.get(connector);

        // 3.按事件处理
        boolean sync = false;
        if(null == parser){
            return sync;
        }
        switch (eventType) {
        case ConnectorConstant.OPERTION_UPDATE:
            sync = parser.update(mappingTask, row);
            break;
        case ConnectorConstant.OPERTION_INSERT:
            sync = parser.insert(mappingTask, row);
            break;
        case ConnectorConstant.OPERTION_DELETE:
            sync = parser.delete(mappingTask, row);
            break;
        default:
            break;
        }
        return sync;
    }

}
